import { ConfigService } from '@nestjs/config'
import moment from 'moment'
import { Server } from 'socket.io'
import { giftConfig } from '../../config/gift'
import { User } from '../../models/User'
import { AppError } from '../../utils/AppError'
import { PaymentService } from '../payment/PaymentService'
import { RedisService } from '../redis/RedisService'
import { RoomStateService } from '../room/RoomStateService'

export class GiftService {
  private io: Server
  private redis: RedisService
  private roomState: RoomStateService
  private payment: PaymentService

  constructor(
    io: Server,
    redisService: RedisService,
    roomStateService: RoomStateService,
    private readonly configService: ConfigService
  ) {
    this.io = io
    this.redis = redisService
    this.roomState = roomStateService
    this.payment = new PaymentService(configService, redisService)
  }

  // 发送礼物
  async sendGift(data: {
    userId: string
    roomId: string
    giftId: string
    count: number
    combo?: boolean
  }) {
    const { userId, roomId, giftId, count = 1, combo = false } = data

    // 获取礼物信息
    const gift = giftConfig.gifts.find((g) => g.id === giftId)
    if (!gift) {
      throw new AppError(400, '礼物不存在')
    }

    // 检查用户余额
    const totalPrice = gift.price * count
    const user = await User.findById(userId)
    if (user.coins < totalPrice) {
      throw new AppError(400, '余额不足，请先充值')
    }

    // 创建礼物记录
    const giftRecord = {
      id: `gift_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
      userId,
      roomId,
      giftId,
      giftName: gift.name,
      count,
      price: gift.price,
      totalPrice,
      combo,
      timestamp: Date.now(),
    }

    // 扣除用户余额
    await User.findByIdAndUpdate(userId, {
      $inc: { coins: -totalPrice },
    })

    // 增加主播收益
    const room = await this.redis.hgetall(`room:${roomId}:info`)
    const anchorShare = Math.floor(totalPrice * giftConfig.anchorShareRate)
    await User.findByIdAndUpdate(room.owner, {
      $inc: {
        coins: anchorShare,
        income: anchorShare,
      },
    })

    // 获取发送者信息
    const sender = await this.getUserInfo(userId)
    const fullGiftRecord = { ...giftRecord, sender }

    // 广播礼物消息
    this.io.to(roomId).emit('gift', fullGiftRecord)

    // 保存礼物记录
    await this.saveGiftRecord(fullGiftRecord)

    // 更新统计信息
    await this.updateStats(roomId, userId, totalPrice)

    // 检查礼物特效
    if (gift.effect) {
      this.io.to(roomId).emit('gift_effect', {
        ...fullGiftRecord,
        effect: gift.effect,
      })
    }

    // 检查成就
    await this.checkAchievements(userId, roomId, totalPrice)

    return fullGiftRecord
  }

  // 获取礼物列表
  async getGiftList(roomId: string) {
    const room = await this.redis.hgetall(`room:${roomId}:info`)
    const anchorLevel = await User.findById(room.owner).select('level')

    // 根据主播等级过滤可用礼物
    return giftConfig.gifts.filter((gift) => gift.minAnchorLevel <= anchorLevel.level)
  }

  // 获取礼物排行榜
  async getGiftRanking(roomId: string, type: 'daily' | 'weekly' | 'monthly' = 'daily') {
    const key = `gift:rank:${roomId}:${this.getRankingKey(type)}`
    const ranking = await this.redis.zrevrange(key, 0, 49)

    const result = []
    for (let i = 0; i < ranking.length; i += 2) {
      const userId = ranking[i]
      const amount = parseInt(ranking[i + 1])
      const user = await User.findById(userId).select('nickname avatar level badges')

      result.push({
        rank: i / 2 + 1,
        userId,
        nickname: user.nickname,
        avatar: user.avatar,
        level: user.level,
        badge: user.badges[0],
        amount,
      })
    }

    return result
  }

  // 获取用户信息
  private async getUserInfo(userId: string) {
    const user = await User.findById(userId).select('nickname avatar level badges vipLevel')

    return {
      userId,
      nickname: user.nickname,
      avatar: user.avatar,
      level: user.level,
      badge: user.badges[0],
      vipLevel: user.vipLevel,
    }
  }

  // 保存礼物记录
  private async saveGiftRecord(record: any) {
    const key = `gift:history:${record.roomId}`
    await this.redis.lpush(key, JSON.stringify(record))
    await this.redis.ltrim(key, 0, giftConfig.history.maxLength - 1)
  }

  // 更新统计信息
  private async updateStats(roomId: string, userId: string, amount: number) {
    const multi = this.redis.multi()
    const today = moment().format('YYYY-MM-DD')

    // 更新房间统计
    multi.hincrby(`room:${roomId}:stats`, 'gift', amount)
    multi.hincrby(`room:${roomId}:stats`, 'totalGift', amount)

    // 更新用户统计
    multi.hincrby(`user:${userId}:stats`, 'gift', amount)
    multi.hincrby(`user:${userId}:stats`, 'totalGift', amount)

    // 更新排行榜
    multi.zincrby(`gift:rank:${roomId}:${today}`, amount, userId)
    multi.zincrby(`gift:rank:${roomId}:${this.getRankingKey('weekly')}`, amount, userId)
    multi.zincrby(`gift:rank:${roomId}:${this.getRankingKey('monthly')}`, amount, userId)

    await multi.exec()
  }

  // 检查成就
  private async checkAchievements(userId: string, roomId: string, amount: number) {
    const achievements = giftConfig.achievements
    const stats = await this.redis.hgetall(`user:${userId}:stats`)

    for (const achievement of achievements) {
      if (
        Number(stats.totalGift) >= achievement.requirement &&
        !(await this.redis.sismember(`user:${userId}:achievements`, achievement.id))
      ) {
        // 发放成就奖励
        await User.findByIdAndUpdate(userId, {
          $inc: { coins: achievement.reward },
          $push: { badges: achievement.badge },
        })

        // 记录成就
        await this.redis.sadd(`user:${userId}:achievements`, achievement.id)

        // 广播成就消息
        this.io.to(roomId).emit('achievement', {
          userId,
          achievement,
        })
      }
    }
  }

  // 获取排行榜Key
  private getRankingKey(type: string): string {
    const now = new Date()
    if (type === 'daily') {
      return moment().format('YYYY-MM-DD')
    } else if (type === 'weekly') {
      return moment().startOf('week').format('YYYY-MM-DD')
    } else {
      return moment().format('YYYY-MM')
    }
  }
}
